package com.sj.purchase.modules.cost.web;

import com.sj.purchase.modules.cost.domain.imei.UniqueCodes;
import com.sj.purchase.modules.cost.domain.imei.Inventory;
import com.sj.purchase.modules.cost.domain.order.InOrder;
import com.sj.purchase.modules.cost.repository.imei.InventoryRepository;
import com.sj.purchase.modules.cost.repository.imei.UniqueCodesRepository;
import com.sj.purchase.modules.cost.repository.order.InOrderRepository;
import com.sj.purchase.modules.cost.service.UniqueCodeService;
import com.sj.purchase.modules.cost.views.uniquecode.*;
import com.sj.purchase.util.DateUtils;
import com.sj.purchase.util.ExcelDownloadUtil;
import com.sj.purchase.util.excel.annotation.ExcelCell;
import com.sj.purchase.util.excel.annotation.ExcelSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 描述:
 * 作者: cuijh.
 * 包名：com.sj.purchase.modules.cost.web
 * 日期: 2018年03月14日 16:42
 * 项目名称: purchase
 * JDK: since 1.8
 */
@RestController
@RequestMapping("api/matching-inventory")
public class MatchingInventoryController {

  @Autowired
  private InventoryRepository repository;

  @Autowired
  private UniqueCodeService service;

  @Autowired
  private InOrderRepository inOrderRepository;

  @Autowired
  private UniqueCodesRepository uniqueCodesRepository;

  List<ExportUniqueCodeData> uniqueCodeDatas = new ArrayList<>();

  /**
   * 导入订单明细表
   * @param date
   * @param oFile
   */
  @PostMapping("/import")
  public ResponseEntity importE(@RequestParam String date,@RequestParam("oExcel") MultipartFile oFile) {
    String oFileName = oFile.getOriginalFilename();
    try {
      InputStream inputStream = oFile.getInputStream();
      ExcelOrders excelOrders = importExcel(oFileName,inputStream, ExcelOrders.class);
      List<UniqueCodes> uniqueCodes = service.checkUniqueCodes(date,excelOrders.getOrders());
      Map<String,UniqueCodes> map = new HashMap<>();
      uniqueCodes.forEach(uniqueCodes1 -> {
        map.put(uniqueCodes1.getUcode(),uniqueCodes1);
      });
      Set<String> keySet = map.keySet();
      List<UniqueCodes> list = new ArrayList<>();
      keySet.forEach(key -> {
        list.add(map.get(key));
      });
      uniqueCodesRepository.save(list);
      return  ResponseEntity.ok(true);
    } catch (Exception e) {
      e.printStackTrace();
      return ResponseEntity.ok("数据处理错误");
    }
  }

  /**
   * 上传唯一码表
   * @param uFile
   */
  @RequestMapping("/uploadUCode")
  public ResponseEntity importExcel(@RequestParam("uExcel") MultipartFile uFile){
    InputStream inputStream = null;
    try {
      inputStream = uFile.getInputStream();
      String uFileName = uFile.getOriginalFilename();
      ExcelUnique excelUnique = importExcel(uFileName,inputStream, ExcelUnique.class);
      return ResponseEntity.ok(excelUnique.getUniqueDTOS());
    } catch (Exception e) {
      return ResponseEntity.ok("上传失败");
    }
  }

  /**
   * 判断后台处理数据是否完成
   */
  @GetMapping("/isCheck")
  public ResponseEntity getSize(){
    String isCheck = !uniqueCodeDatas.isEmpty() ? "success":"error";
    return ResponseEntity.ok(isCheck);
  }

  /**
   * 导出唯一码数据表
   */
  @GetMapping("/excel")
  public void exportUniqueCode(){
    String excelName = new SimpleDateFormat("yyyy-MM-dd").format(new Date())+"唯一码";
    ExcelDownloadUtil.easyPoi(excelName, ExportUniqueCodeData.class,uniqueCodeDatas);
    uniqueCodeDatas.clear();
  }

  /**
   * 通过唯一码获取所需数据
   * @param uniqueDTOS
   * @throws IOException
   */
  @PostMapping("/inventory")
  public void getInven(@RequestBody List<Unique> uniqueDTOS){
    Set<String> uCodes = new HashSet<>();
    uniqueDTOS.forEach(unique -> {
      uCodes.add(unique.getuCode());
    });
    uniqueCodeDatas = findInven(uCodes);
  }

  /**
   * 根据唯一码查询
   * @param uCodes
   * @return
   */
  private List<ExportUniqueCodeData> findInven(Set<String> uCodes){
    List<ExportUniqueCodeData> uniqueCodeData = new ArrayList<>();
    for (String uCode:uCodes) {
      List<Inventory> inventories = repository.findById_Imei(uCode);
      if(inventories.size() > 0){
        inventories.forEach(inventory -> {
          ExportUniqueCodeData exportUniqueCodeData = new ExportUniqueCodeData();
          exportUniqueCodeData.setUcode(uCode);
          exportUniqueCodeData.setInOrderNo(inventory.getInOrderNo());
          exportUniqueCodeData.setShopName(inventory.getShopName());
          InOrder inorder = inOrderRepository.findByOrderNo(inventory.getInOrderNo());
          String supplierName = "";
          if (inorder != null) {
            supplierName = (inorder.getSupplierName() == null) ? "" : inorder.getSupplierName();
          } else {
            supplierName = "";
          }
          exportUniqueCodeData.setSupplierName(supplierName);
          exportUniqueCodeData.setCostPrice(String.valueOf(inventory.getCostPrice()));
          exportUniqueCodeData.setInStockDatedate(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(inventory.getId().getInStockDate()));
          uniqueCodeData.add(exportUniqueCodeData);
        });
      }
    }
    return uniqueCodeData;
  }

  /**
   * 按日期查询
   * @param date
   * @param pageable
   * @return
   */
  @GetMapping()
  public Page<UniqueCodes> getExportList(String date, Pageable pageable) {
    Date date1 = DateUtils.dateFormat(date);
    Date start = DateUtils.getStartOfDay(date1);
    Date end = DateUtils.getEndOfDay(date1);
    Page<UniqueCodes> uniqueCodesPage = uniqueCodesRepository.findByOutStockDateBetweenAndOrderIdIsNotNull(start,end,pageable);
    return uniqueCodesPage;
  }

  /**
   * 导出
   * @param date
   */
  @GetMapping("/export")
  public void exportE(@RequestParam String date) {
    Date start = DateUtils.getStart(DateUtils.dateFormat(date));
    Date end = DateUtils.getEnd(DateUtils.dateFormat(date));
    uniqueCodesRepository.deleteAllByOutStockDateBetweenAndOrderIdIsNull(start,end);
    ExcelDownloadUtil.easyPoi(date + "唯一码", UniqueCodes.class, getExportList(date,null).getContent().stream().collect(Collectors.toList()));
  }

  /**
   * 手动同步导出唯一码数据
   */
  @GetMapping("/sync")
  public void sync(@RequestParam String date) {
    service.saveUniqueCode(DateUtils.dateFormat(date));
  }

  /**
   * 导入表生成集合
   *
   * @param inputStream
   * @param excelClazz
   * @param <T>
   * @return
   * @throws IOException
   * @throws InstantiationException
   * @throws IllegalAccessException
   */
  private <T> T importExcel(String fileName,InputStream inputStream, Class<? extends T> excelClazz) throws IOException, InstantiationException, IllegalAccessException {
    String type = fileName.substring(fileName.lastIndexOf("."));
    Workbook workbook = null;
    if (type.equals(".xls")){
      workbook =  new HSSFWorkbook(inputStream);
    }if (".xlsx".equals(type)){
      workbook = new XSSFWorkbook(inputStream);
    }
    Object excelObj = excelClazz.newInstance();//实例化对象
    Field[] fields = excelClazz.getDeclaredFields();//获取类中所有的属性
    for (Field field : fields) {
      if (field.isAnnotationPresent(ExcelSheet.class)) {
        ExcelSheet sheet = field.getAnnotation(ExcelSheet.class);
//       默认只支持 List
        ParameterizedType pt = (ParameterizedType) field.getGenericType();
        Class clz = (Class) pt.getActualTypeArguments()[0];
        field.setAccessible(true);
        field.set(excelObj, this.sheet(workbook, sheet.value(), clz));
      }
    }
    return (T) excelObj;
  }

  /**
   * 获取表中的Sheet数据生成list
   *
   * @param workbook
   * @param sheetIndex
   * @param clazz
   * @return
   * @throws IllegalAccessException
   * @throws InstantiationException
   */
  private List<? super Object> sheet(Workbook workbook, int sheetIndex, Class<?> clazz) throws IllegalAccessException, InstantiationException {
    Sheet sheet = workbook.getSheetAt(sheetIndex);
    List<? super Object> rowList = new ArrayList<>(sheet.getLastRowNum());
    Field[] fields = clazz.getDeclaredFields();
    for (int j = 0; j < sheet.getLastRowNum() + 1; j++) {// getLastRowNum，获取最后一行的行标
      Object o = clazz.newInstance();
      rowList.add(o);
      Row row = sheet.getRow(j);
      for (Field field : fields) {
        if (field.isAnnotationPresent(ExcelCell.class)) {
          ExcelCell excelCell = field.getAnnotation(ExcelCell.class);
          int cellIndex = excelCell.value();
          if (row != null) {
            if (row.getCell(cellIndex) != null) {
              row.getCell(cellIndex).setCellType(Cell.CELL_TYPE_STRING);
            }
            if (row.getCell(cellIndex) != null && !row.getCell(cellIndex).equals("")) {
              String cellValue = row.getCell(cellIndex).getStringCellValue();
              field.setAccessible(true);
              field.set(o, cellValue);
            }
          }
        }
      }
    }
    return rowList;
  }
}
